// @import
import MsgRecognizer from "./MsgRecognizer";
import OutParam from "../util/OutParam";
import mod_protobufjs = require("protobufjs/minimal");

/**
 * 消息编解码器
 */
export default class MsgCodec {
    /**
     * 编码
     * 
     * @param nMsgCode 消息代号
     * @param oMsgBody 消息体
     * @returns 字节数组
     */
    encode(nMsgCode: number, oMsgBody: any): Uint8Array {
        if (null == oMsgBody) {
            return null;
        }

        if (nMsgCode < 0) {
            return null;
        }

        // 创建输出流
        let oWriter = mod_protobufjs.Writer.create();

        // 写出消息代号, 
        // XXX 注意: 一定要使用固定长度无符号的整数
        oWriter.fixed32(nMsgCode);

        // 编码为字节数组
        let oByteArray: Uint8Array = oMsgBody.constructor.encode(
            oMsgBody, oWriter
        ).finish();

        return oByteArray;
    }

    /**
     * 解码
     * 
     * @param oByteArray 字节数组
     * @param out_oMsgCode ( 输出参数 ) 消息代号
     * @param out_oMsgName ( 输出参数 ) 消息名称
     * @returns 消息对象
     */
    decode(oByteArray: Uint8Array, out_oMsgCode: OutParam<number> = null, out_oMsgName: OutParam<string> = null): any {
        if (!oByteArray ||
            !oByteArray.byteLength) {
            return null;
        }

        // 创建读取流
        let oReader = mod_protobufjs.Reader.create(oByteArray);

        // 获取消息编码
        let nMsgCode: number = oReader.fixed32();

        if (null != out_oMsgCode) {
            out_oMsgCode.put(nMsgCode);
        }

        // 获取消息类
        let oMsgClazz: any = MsgRecognizer.getMsgClazzByMsgCode(nMsgCode, out_oMsgName);

        if (null == oMsgClazz) {
            return null;
        }

        return oMsgClazz.decode(oReader);
    }
}
